
import static org.junit.Assert.*;

import java.util.Arrays;

import org.junit.Test;

public class TestWorkSchedule {

	private WorkSchedule ws = new WorkSchedule(10);
	
	public void tearDown() {
		
		ws = new WorkSchedule(10);
		
	}
	
	@Test
	public void testSetRequiredNumber() {
		
		/* Deriving boundary inputs from the truth table, where
		 */		
//		Start = 0	Endtime = size-1	Starttime = endtime	#employees = 0
//      ==================================================================
		WorkSchedule ws = new WorkSchedule(1);
		//SIZE 1
//		0           TRUE 0 = 1 - 1      TRUE                0
		ws.setRequiredNumber(0, 0, 0);
		assertTrue(ws.readSchedule(0).requiredNumber == 0); //OK

//		0           TRUE 0 = 1 - 1      TRUE                1
		ws.setRequiredNumber(1, 0, 0);
		assertFalse(ws.readSchedule(0).requiredNumber == 1); //should not change
		
		ws = new WorkSchedule(2);
		//SIZE 2
//		0           TRUE 1 = 2 - 1      FALSE               0
		ws.setRequiredNumber(0, 0, 1);
		assertTrue(ws.readSchedule(0).requiredNumber == 0); //OK
		
//		0           TRUE 1 = 2 - 1      FALSE               1
		ws.setRequiredNumber(1, 0, 1);
		assertTrue(ws.readSchedule(0).requiredNumber == 1); //OK
		
//		0           FALSE 0 != 2 - 1    TRUE                0
		ws.setRequiredNumber(0, 0, 0);
		assertTrue(ws.readSchedule(0).requiredNumber == 0); //OK
		
//		0           FALSE 0 != 2 - 1    TRUE                1
		ws.setRequiredNumber(1, 0, 0);
		assertFalse(ws.readSchedule(0).requiredNumber == 1); //should not change
		
//		1           TRUE  1 = 2 - 1     TRUE                0
		ws.setRequiredNumber(0, 1, 1);
		assertTrue(ws.readSchedule(1).requiredNumber == 0); //OK
		
//		1           TRUE  1 = 2 - 1     TRUE                1
		ws.setRequiredNumber(1, 1, 1);
		assertFalse(ws.readSchedule(1).requiredNumber == 1); //should not change
		
//		1           FALSE 2 != 2 - 1    FALSE               0
		ws.setRequiredNumber(0, 1, 2);
		assertTrue(ws.readSchedule(1).requiredNumber == 0); //OK
		
//		1           FALSE 2 != 2 - 1    FALSE               1	
		ws.setRequiredNumber(1, 1, 2);
		assertTrue(ws.readSchedule(1).requiredNumber == 1); //OK
        
		ws = new WorkSchedule(3);
        //SIZE 3
//		0           FALSE 1 != 3 - 1    FALSE               0
		ws.setRequiredNumber(0, 0, 1);
		assertTrue(ws.readSchedule(0).requiredNumber == 0); //OK
		
//		0           FALSE 1 != 3 - 1    FALSE               1
		ws.setRequiredNumber(1, 0, 1);
		assertTrue(ws.readSchedule(0).requiredNumber == 1); //OK

//		1           TRUE  2 = 3 - 1     FALSE               0
		ws.setRequiredNumber(0, 1, 2);
		assertTrue(ws.readSchedule(1).requiredNumber == 0); //OK
//
//		1           TRUE  2 = 3 - 1     FALSE               1
		ws.setRequiredNumber(1, 1, 2);
		assertTrue(ws.readSchedule(1).requiredNumber == 1); //OK
//
//		1           FALSE 1 != 3 - 1    TRUE                0
		ws.setRequiredNumber(0, 1, 1);
		assertTrue(ws.readSchedule(1).requiredNumber == 0); //OK

//		1           FALSE 1 != 3 - 1    TRUE                1
		ws.setRequiredNumber(1, 1, 1);
		assertFalse(ws.readSchedule(1).requiredNumber == 1); //OK
//

	}
	
	@Test
	public void testSetRequiredNumber2(){
		
		// Bug found, i should be between 0 and 0 (start time and end time)
		// according to the specification but it still change the schedule
		// but it should not change. 
		ws.setRequiredNumber(1, 0, 0);
		assertFalse(ws.readSchedule(0).requiredNumber == 1);
	}
	
	@Test
	public void testSetRequiredNumber3(){
		
		// Should pass since we are not really trying anything. We are trying 
		// to add 0 workers between time 0 and 0. 
		ws.setRequiredNumber(0, 0, 0);
		assertTrue(ws.readSchedule(0).requiredNumber == 0);
	}

	@Test
	public void testAddWorkingPeriod() {

		ws.setRequiredNumber(1, 1, 4); // 1 employees between 1 - 4
		ws.setRequiredNumber(2, 5, 8); // 2 employees between 5 - 8
		
		assertTrue(ws.readSchedule(1).requiredNumber == 1);
		
		//Test setting up initial workers
		assertTrue(ws.addWorkingPeriod("Erik", 1, 4));
		
		assertTrue(ws.addWorkingPeriod("Anders", 5, 8));
		assertTrue(ws.addWorkingPeriod("Doe", 5, 8));
		
		
	}
	
	@Test
	public void testAddWorkingperiod2(){
		
		//Try adding a worker where no one is needed
		assertFalse(ws.addWorkingPeriod("Johan", 0, 0));
		assertFalse(ws.addWorkingPeriod("John", 9, 9));
	
	}
	
	@Test
	public void testAddWorkingPeriod3(){
		
		//Try adding a worker where it is full
		assertFalse(ws.addWorkingPeriod("JJ", 1, 3));
		assertFalse(ws.addWorkingPeriod("JJ", 7, 8));
		
	}
	
	@Test
	public void testAddWorkingPeriod4(){
		
		//Try adding a worker who is already working that period
		assertFalse(ws.addWorkingPeriod("Erik", 3, 4));
		assertFalse(ws.addWorkingPeriod("Doe", 7, 8));
	}
	@Test 
	public void testAddWorkingPeriod5(){
		
		//Bug, can add a person with an endtime < 0, expected fail
		ws.setRequiredNumber(1, 0, 2);
		assertFalse(ws.addWorkingPeriod("Jo", 0, -1));
	}
	
	@Test
	public void testAddWorkingPeriod6(){
		
		//Bug, can add a person with start time > endtime, expected fail
		// start > end
		ws.setRequiredNumber(1, 3, 4);
		assertFalse(ws.addWorkingPeriod("Jo", 4, 2));

	}
	
	@Test
	public void testWorkingEmployees2(){
		ws.setRequiredNumber(2, 0, 2); // 2 employees, 0 - 2
		ws.addWorkingPeriod("Erik", 0, 2);
		ws.addWorkingPeriod("Johan", 0, 2);
		
		String[] expectedPer1 = {"Erik","Johan"};
		String[] ans1 = ws.workingEmployees(0, 2);
		
		assertTrue(expectedPer1[0].equals(ans1[0]));
		assertTrue(expectedPer1[1].equals(ans1[1]));
		
	}
	
	@Test
	public void testWorkingEmployees3() {
		
		ws.setRequiredNumber(1, 3, 5); // 1 employee, 3 - 5
		ws.setRequiredNumber(1, 6, 9); // 1 employee, 6 - 9
		ws.addWorkingPeriod("Anders", 3, 5);
		ws.addWorkingPeriod("Johan", 6, 9);
		
		String[] expectedPer2 = {"Anders"};
		String[] expectedPer3 = {"Johan"};

		String[] ans2 = ws.workingEmployees(3, 5);
		String[] ans3 = ws.workingEmployees(6, 8);

		assertTrue(Arrays.equals(ans2, expectedPer2));
		assertTrue(Arrays.equals(ans3, expectedPer3));
	}
	
	@Test
	public void testWorkingEmployees4() {
		
		// Try fetching employees from where there has not been added any
		String[] ans4 = ws.workingEmployees(9, 9);
		String[] ans5 = ws.workingEmployees(0, 0);
		
		String[] expected = {}; // Should not contain any employees
		
		assertTrue(Arrays.equals(ans4, expected));
		assertTrue(Arrays.equals(ans5, expected));

	}
	
	@Test 
	public void testWorkingEmployees5() {
		ws.setRequiredNumber(2, 0, 2); // 2 employees, 0 - 2
		ws.addWorkingPeriod("Erik", 0, 2);
		ws.addWorkingPeriod("Johan", 0, 2);
		
		String[] expected = {};
		
		String[] ans6 = ws.workingEmployees(2, 1); 
										// Bug if start >end. Expected fail
		assertTrue(Arrays.equals(expected, ans6)); 
	}

	@Test
	public void testNextIncomplete2(){
		
		ws.setRequiredNumber(2, 0, 2);
		ws.setRequiredNumber(1, 3, 5);
		ws.setRequiredNumber(1, 6, 9);

		ws.addWorkingPeriod("Erik", 0, 2);
		ws.addWorkingPeriod("Johan", 0, 2);
		ws.addWorkingPeriod("Anders", 3, 5);
		
		// from 0 - 2 it is covered
		// from 3 - 5 it is covered
		// from 6 - 9 it is not covered
		
		// test with 0<= currenttime <= size-1
				for(int currenttime = 0; currenttime < 10; currenttime++){

					if(currenttime >= 0 && currenttime <=5){
						//covered but not from 6 so should return 6
						assertTrue(ws.nextIncomplete(currenttime) == 6);
			
					}
				}
	}
	@Test
	public void testNexIncomplete3(){
		
		ws.setRequiredNumber(2, 0, 2);
		ws.setRequiredNumber(1, 3, 5);
		ws.setRequiredNumber(1, 6, 9);

		ws.addWorkingPeriod("Erik", 0, 2);
		ws.addWorkingPeriod("Johan", 0, 2);
		ws.addWorkingPeriod("Anders", 3, 5);
		ws.addWorkingPeriod("Anders", 6, 9); // now all is covered should be -1
		
		//The slots are covered from 0 - 9

		for(int currenttime = 0; currenttime < 10; currenttime++)
		assertTrue(ws.nextIncomplete(currenttime) == -1); // Should pass
		
	}

}
